package models

func NewEntityInfo(dalStru *StructInfo, diyDo *InterfaceInfo, pkg *Package) *EntityInfo {
	idFields := make([]*FieldInfo, 0)
	for _, field := range dalStru.Fields {
		if field.Tag == "Id" {
			idFields = append(idFields, field)
		}
	}
	if len(idFields) == 0 {
		for _, field := range dalStru.Fields {
			if field.Name == "Id" {
				idFields = append(idFields, field)
			}
		}
	}
	if len(idFields) == 0 {
		panic("no id field found")
	}
	return &EntityInfo{
		IdFields:          idFields,
		DalStruct:         dalStru,
		DalInterface:      createDalInterface(dalStru, diyDo, pkg),
		DalDIYDoInterface: diyDo,
	}
}

func createDalInterface(dalStru *StructInfo, diyDo *InterfaceInfo, pkg *Package) *InterfaceInfo {
	modelName := dalStru.ModelName()
	dalIntf := &InterfaceInfo{
		ParentInterface: diyDo,
		Name:            modelName + "Do",
		Package:         &pkg.PackageInfo,
		Methods:         make([]*MethodInfo, 0),
		Annotations:     NewAnnotations(),
	}
	dalIntf.AddMethod(createBaseCrudMethod("Create"))
	dalIntf.AddMethod(createBaseCrudMethod("Update"))
	dalIntf.AddMethod(createBaseCrudMethod("Delete"))
	dalIntf.AddMethod(createBaseCrudMethod("Find"))

	for _, field := range dalStru.Fields {
		dalIntf.AddMethod(createGetterMethod(field.Name, field.Type))
		dalIntf.AddMethod(createSetterMethod(field.Name, field.Type))
	}

	return dalIntf
}

func createBaseCrudMethod(name string) *MethodInfo {
	return &MethodInfo{
		Name:    name,
		Params:  []*FieldInfo{{Type: "context.Context"}},
		Results: []*FieldInfo{{Type: "error"}},
	}
}

func createGetterMethod(name string, t string) *MethodInfo {
	return &MethodInfo{
		Name:    "Get" + name,
		Params:  []*FieldInfo{},
		Results: []*FieldInfo{{Type: t}},
	}
}

func createSetterMethod(name string, t string) *MethodInfo {
	return &MethodInfo{
		Name:    "Set" + name,
		Params:  []*FieldInfo{{Type: t}},
		Results: []*FieldInfo{},
	}
}

type EntityInfo struct {
	IdFields          []*FieldInfo
	DalStruct         *StructInfo
	DalDIYDoInterface *InterfaceInfo
	DalInterface      *InterfaceInfo
}

func (e *EntityInfo) Column(name string) *FieldInfo {
	for _, field := range e.DalStruct.Fields {
		if field.Name == name {
			return field
		}
	}
	return nil
}
